﻿using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Threading;
using Wpf.Ui;
using WpfMvvmTemplate.WPFUI.Common;
using WpfMvvmTemplate.WPFUI.Tools.Helper;
using WpfMvvmTemplate.WPFUI.ViewModels.Main;
using WpfMvvmTemplate.WPFUI.ViewModels.Pages;
using WpfMvvmTemplate.WPFUI.Views.Main;
using WpfMvvmTemplate.WPFUI.Views.Pages;

namespace WpfMvvmTemplate.WPFUI
{
    public partial class App
    {
        //IOC容器
        public IServiceProvider Services { get; }

        public App()
        {
            Services = ConfigureServices();

            #region 全局异常捕获

            //UI线程未捕获异常处理事件（UI主线程）
            this.DispatcherUnhandledException += (s, e) =>
            {
                if(e.Exception is Exception ex)
                {
                    LogHelper.WriteLog($"{ex.ToString()}");
                    e.Handled = true;//表示异常已处理，可以继续运行
                }
            };

            //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)
            AppDomain.CurrentDomain.UnhandledException += (s, e) =>
            {
                if(e.ExceptionObject is Exception ex)
                    LogHelper.WriteLog(ex.ToString());
            };

            //Task线程内未捕获异常处理事件
            TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                if(e.Exception is Exception ex)
                {
                    LogHelper.WriteLog($"{ex.ToString()}");
                    e.SetObserved(); // 标记异常已被处理，避免程序崩溃
                }
            };

            #endregion

            #region 单实例运行

            //判断程序是否已经启动
            var ProcessName = Assembly.GetExecutingAssembly().GetName().Name;//程序集名称
            Process currentProcess = Process.GetCurrentProcess();//当运行的新进程

            // 通过程序集名称判断是否有进程已运行
            Process[] ps = Process.GetProcessesByName(ProcessName);

            // 因为新进程名也是ProcessName，所以ps的Length大于1时才是有多个进程
            if(ps.Length > 1)
            {
                foreach(var item in ps)
                {
                    // 找到非当前新进程的 MessageConstruction 进程对象
                    if(item.Id != currentProcess.Id)
                    {
                        //关闭之前的进程
                        item.Kill();
                    }
                }
            }

            #endregion 单实例运行    
        }


        public new static App Current => (App)Application.Current;

        //容器注册
        private static IServiceProvider ConfigureServices()
        {
            var services = new ServiceCollection();

            services.AddSingleton<MainWindowView>();
            services.AddSingleton<MainWindowViewModel>();

            services.AddSingleton<INavigationService, NavigationService>();
            services.AddSingleton<ISnackbarService, SnackbarService>();
            services.AddSingleton<IContentDialogService, ContentDialogService>();

            services.AddSingleton<DashboardPage>();
            services.AddSingleton<DashboardViewModel>();
            services.AddSingleton<DataPage>();
            services.AddSingleton<DataPageViewModel>();
            services.AddSingleton<SettingsPage>();
            services.AddSingleton<SettingsViewModel>();

            //注册日志服务
            services.AddSingleton<ILogger>((s) =>
            {
                var date = DateTime.Now.ToString("yyyy-MM-dd");
                var logFile = Path.Combine("Logs/", date + ".txt");

                return new LoggerConfiguration()
                            .MinimumLevel.Debug()
                            .WriteTo.File(logFile, retainedFileCountLimit: null) //自动换行
                            .CreateLogger();
            });

            return services.BuildServiceProvider();
        }

        /// <summary>
        /// 程序启动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            var navigationWindow = Services.GetService<MainWindowView>();
            navigationWindow!.Loaded += OnNavigationWindowLoaded;
            navigationWindow.Show();

            //记录软件启动模式
            string AppName = AppDomain.CurrentDomain.FriendlyName;

#if DEBUG
            GlobalStaticData.Logger.Information($"软件 {AppName} 以 Debug 模式启动！");
#else
            GlobalStaticData.Logger.Information($"软件 {AppName} 以 Release 模式启动！");
#endif
        }

        /// <summary>
        /// 默认加载第一项page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnNavigationWindowLoaded(object sender, RoutedEventArgs e)
        {
            if(sender is not MainWindowView navigationWindow) { return; }
            navigationWindow.NavigationView.Navigate(typeof(DashboardPage));
        }

    }
}
